package wireTestApp

import (
	"UserApp/api"
	"UserApp/middleware"
	"context"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/wire"
	xerrors "github.com/pkg/errors"
	"golang.org/x/sync/errgroup"
	"net/http"
	_ "net/http/pprof"
	"os"
	"time"
)

var ProviderSet = wire.NewSet(ProviderApp)

type App struct {
	appServer   *http.Server
	debugServer *http.Server
	quit        chan os.Signal
}

func setHttpMux(a *api.UserApi) http.Handler {
	e := gin.New()
	e.Use(middleware.ErrorHandle)
	e.POST("/user", a.CreateUser)
	e.GET("/user", a.GetUser)
	e.PATCH("/user", a.UpdateUser)
	e.DELETE("/user", a.DeleteUser)

	return e
}

func ProviderApp(a *api.UserApi) *App {
	e := setHttpMux(a)
	s := &http.Server{Addr: ":8080", Handler: e}
	d := &http.Server{Addr: ":8081", Handler: nil}
	quit := make(chan os.Signal, 0)
	return &App{s, d, quit}
}

func (a *App) Run() error {
	eg, ctx := errgroup.WithContext(context.Background())

	//开启appServer
	eg.Go(func() error {
		err := a.appServer.ListenAndServe()
		return err
	})

	//开启debugServer
	eg.Go(func() error {
		err := a.debugServer.ListenAndServe()
		return err
	})

	//监控退出信号是否触发,退出appServer
	eg.Go(func() error {
		select {
		case <-ctx.Done():
			ctxT, cancel := context.WithTimeout(context.Background(), time.Second*3)
			defer cancel()
			return a.appServer.Shutdown(ctxT)
		}
	})

	//监控退出信号是否触发,退出debugServer
	eg.Go(func() error {
		select {
		case <-ctx.Done():
			ctxT, cancel := context.WithTimeout(context.Background(), time.Second*3)
			defer cancel()
			return a.debugServer.Shutdown(ctxT)
		}
	})

	//监控退出信号
	eg.Go(func() error {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case sign := <-a.quit:
			return xerrors.Wrap(errors.New(fmt.Sprintf("%v", sign)), fmt.Sprintf("to be quited, reason is : get an %v signal", sign))
		}
	})

	return eg.Wait()
}
